package main

import (
	"context"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"time"

	"awesomeProject/rpc/user/config"
	"github.com/dgrijalva/jwt-go"
	"gorm.io/gorm"
)

// User 用户表
type User struct {
	gorm.Model
	UserId   uint32 `gorm:"primarykey"`      //用户ID
	Username string `gorm:"unique;not null"` // 用户名
	Password string `gorm:"not null"`        // 密码
	Role     uint8  `gorm:"not null"`        // 权限等级
}

// UserServiceImpl implements the last service interface defined in the IDL.
type UserServiceImpl struct{}

// 注册
/* **@param ctx 上下文
 **@param username 用户名
 **@param passwordHash 密码哈希值
 **@param role 用户权限等级
 **@return resp 用户信息 DTO
 **@return err 错误信息 */
func (s *UserServiceImpl) Register(ctx context.Context, username string, passwordHash string, role uint8) (token string, err error) {
	// 获取全局配置
	cfg, err := config.LoadConfig("config.yaml")
	if err != nil {
		return "failed to load config", fmt.Errorf("failed to load config: %w", err)
	}

	// 1. 加密密码
	encryptedPassword, err := encryptPassword(passwordHash, cfg.Security.EncryptionKey)
	if err != nil {
		return "failed to encrypt password", fmt.Errorf("failed to encrypt password: %w", err)
	}

	// 2. 写入数据库
	newUser := User{
		Username: username,
		Password: encryptedPassword,
		Role:     role,
	}
	if err := DB.Create(&newUser).Error; err != nil {
		return "failed to create user in database", fmt.Errorf("failed to create user in database: %w", err)
	}

	// 3. 生成 JWT 令牌
	token, err = generateJWT(username, role, newUser.UserId, cfg.Security.JwtSecret) // 传递 newUser.UserId
	if err != nil {
		return "failed to generate JWT token", fmt.Errorf("failed to generate JWT token: %w", err)
	}

	// 返回 JWT 令牌
	return token, nil
}

// 加密
// /* **@param password 待加密的密码
//
//	**@param key 加密密钥
//	**@return string 加密后的密码
//	**@return error 错误信息 */
func encryptPassword(password, key string) (string, error) {
	block, err := aes.NewCipher([]byte(key))
	if err != nil {
		return "", err
	}

	// 创建一个随机的初始化向量 (IV)
	ciphertext := make([]byte, aes.BlockSize+len(password))
	iv := ciphertext[:aes.BlockSize]
	if _, err := rand.Read(iv); err != nil {
		return "", err
	}

	// 使用 CFB 模式加密
	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], []byte(password))

	// 返回 Base64 编码的加密结果
	return base64.URLEncoding.EncodeToString(ciphertext), nil
}

// JWT生成
// /* **@param username 用户名
//
//	**@param role 用户权限等级
//	**@param userId 用户ID
//	**@param secret JWT 密钥
//	**@return string 生成的 JWT 令牌
//	**@return error 错误信息 */
func generateJWT(username string, role uint8, userId uint32, secret string) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"username": username,
		"role":     role,
		"userId":   userId,                                // 添加 userId 到 JWT 声明中
		"exp":      time.Now().Add(time.Hour * 24).Unix(), // 令牌有效期为 24 小时
	})

	// 使用密钥签名并返回 JWT
	return token.SignedString([]byte(secret))
}

// 验证
// /* **@param ctx 上下文
//
//	**@param username 用户名
//	**@param passwordHash 密码哈希值
//	**@return string JWT 令牌
//	**@return error 错误信息 */
func (s *UserServiceImpl) Authenticate(ctx context.Context, username string, passwordHash string) (resp string, err error) {
	// 获取全局配置
	cfg, err := config.LoadConfig("config.yaml")
	if err != nil {
		return "", fmt.Errorf("failed to load config: %w", err)
	}

	// 1. 查询用户信息
	var user User
	if err := DB.Where("username = ?", username).First(&user).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return "", fmt.Errorf("user not found")
		}
		return "", fmt.Errorf("failed to query user from database: %w", err)
	}

	// 2. 解密存储的密码
	decryptedPassword, err := decryptPassword(user.Password, cfg.Security.EncryptionKey)
	if err != nil {
		return "", fmt.Errorf("failed to decrypt password: %w", err)
	}

	// 3. 验证密码是否一致
	if decryptedPassword != passwordHash {
		return "", fmt.Errorf("invalid password")
	}

	// 4. 生成 JWT 令牌
	token, err := generateJWT(username, user.Role, user.UserId, cfg.Security.JwtSecret) // 传递 user.UserId
	if err != nil {
		return "", fmt.Errorf("failed to generate JWT token: %w", err)
	}

	// 返回 JWT 令牌
	return token, nil
}

// 解密
// /* **@param encryptedPassword 加密后的密码
//
//	**@param key 解密密钥
//	**@return string 解密后的密码
//	**@return error 错误信息 */
func decryptPassword(encryptedPassword, key string) (string, error) {
	// 解码 Base64 编码的加密结果
	ciphertext, err := base64.URLEncoding.DecodeString(encryptedPassword)
	if err != nil {
		return "", err
	}

	// 创建 AES 加密块
	block, err := aes.NewCipher([]byte(key))
	if err != nil {
		return "", err
	}

	// 提取 IV
	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	// 使用 CFB 模式解密
	stream := cipher.NewCFBDecrypter(block, iv)
	stream.XORKeyStream(ciphertext, ciphertext)

	// 返回解密后的密码
	return string(ciphertext), nil
}
